/*
 * Copyright (c) 2013, Klaus Hauschild
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification, are permitted provided
 * that the following conditions are met:
 *
 *   * Redistributions of source code must retain the above copyright notice, this list of conditions and
 *     the following disclaimer.
 *
 *   * Redistributions in binary form must reproduce the above copyright notice, this list of conditions
 *     and the following disclaimer in the documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */
package de.hauschild.utilsn.core.sprite;

import java.util.HashMap;
import java.util.Map;

import playn.core.util.Callback;
import de.hauschild.utilsn.core.animation.Animation;
import de.hauschild.utilsn.core.animation.Animations;

/**
 * @since 0.1.0
 * 
 * @author Klaus Hauschild
 */
public abstract class Sprites {

  public static class AnimationDescription {

    private final int millisPerFrame;
    private final String[] images;
    private final SpritePhase phase;

    public AnimationDescription(final SpritePhase phase, final int frameCount, final int millisPerFrame) {
      this.phase = phase;
      images = new String[frameCount];
      for (int i = 0; i < frameCount; i++) {
        images[i] = String.format("%s_%s.png", phase, i);
      }
      this.millisPerFrame = millisPerFrame;
    }

    public String[] getImages() {
      return images;
    }

    public int getMillisPerFrame() {
      return millisPerFrame;
    }

    public SpritePhase getPhase() {
      return phase;
    }

  }

  public static void load(final String directory, final AnimationDescription[] animationDescriptions,
      final Callback<Sprite> callback) {
    final Animation[] animations = new Animation[animationDescriptions.length];
    for (int i = 0; i < animationDescriptions.length; i++) {
      final int index = i;
      Animations.load(getImages(directory, animationDescriptions[i].getImages()),
          animationDescriptions[i].getMillisPerFrame(), true, new Callback<Animation>() {

            @Override
            public void onFailure(final Throwable cause) {
              callback.onFailure(cause);
            }

            @Override
            public void onSuccess(final Animation result) {
              animations[index] = result;
              if (animationsReady(animations)) {
                callback.onSuccess(new SpriteImpl(getPhases(animationDescriptions, animations),
                    animationDescriptions[0].getPhase()));
              }
            }

            private boolean animationsReady(final Animation[] animations) {
              for (final Animation animation : animations) {
                if (animation == null) {
                  return false;
                }
              }
              return true;
            }

            private Map<SpritePhase, Animation> getPhases(final AnimationDescription[] animationDescriptions,
                final Animation[] animations) {
              final Map<SpritePhase, Animation> phases = new HashMap<SpritePhase, Animation>();
              for (int i = 0; i < animationDescriptions.length; i++) {
                phases.put(animationDescriptions[i].getPhase(), animations[i]);
              }
              return phases;
            }

          });
    }
  }

  private static String[] getImages(final String directory, final String[] images) {
    final String[] result = new String[images.length];
    for (int i = 0; i < images.length; i++) {
      result[i] = String.format("%s/%s", directory, images[i]);
    }
    return result;
  }

}
